﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Compilex.Syntatic.Declarations
{
    public class VariableDeclaration
    {
        private SyntaticContext Context { get; set; }
        public VariableDescriptor Descriptor { get; set; }
        public Symbol Symbol { get; set; }
        public string Identifier { get; set; }


        public VariableDeclaration(SyntaticContext context)
        {
            this.Context = context;
        }

        public void AddDefaultValue()
        {
            if (Descriptor.IsArray)
            {
                throw new SyntaticException("Vetores não podem ser inicializados na declaração.");
            }
            Context.Assignment.StartOrdinaryVariableLHS();            
        }

        public void StartFinishVariable()
        {
            this.Descriptor = new VariableDescriptor();
            Descriptor.IsArray = false;
            Descriptor.Size = 0;
            Identifier = Context.CurrentToken;
            AssertVariableUndeclaredCurrentScope(Identifier);

            Descriptor.Type = SymbolTableHelper.SymbolTypeFromString(
                Context.SyntaticStack.Pop(), Context);

            this.Symbol = new Symbol(Identifier, SymbolClass.Variavex, Descriptor);

            Context.ScopeManager.CurrentScope.SymbolTable.Add(Identifier,
                this.Symbol);

            Context.PushCurrentToken();
            if(SymbolTableHelper.IsGlobalSymbol(Symbol, Context))
                Context.CommandBlockStack.Current.CodeGenerator.AddVariable(this.Symbol);
        }

        

        public void StartFinishArray()
        {
            this.Descriptor = new VariableDescriptor();
            Descriptor.IsArray = true;
            Identifier = Context.CurrentToken;
            AssertVariableUndeclaredCurrentScope(Identifier);

            string bracket = Context.SyntaticStack.Pop();
            string strSize = Context.SyntaticStack.Pop();
            int size;
            if (Int32.TryParse(strSize, out size))
            {
                if (size >= 0)
                {
                    Descriptor.Size = size;
                    bracket = Context.SyntaticStack.Pop();
                    string type = Context.SyntaticStack.Pop();
                    Descriptor.Type = SymbolTableHelper.SymbolTypeFromString(type, Context);
                    
                    this.Symbol = new Symbol(Identifier, SymbolClass.Vetex, Descriptor);

                    Context.ScopeManager.CurrentScope.SymbolTable.Add(Identifier,
                        this.Symbol);
                    if (SymbolTableHelper.IsGlobalSymbol(Symbol, Context))
                        Context.CommandBlockStack.Current.CodeGenerator.AddGlobalArray(this.Symbol);
                }
                else
                {
                    throw new SyntaticException("O tamanho de um vetor deve ser maior do que zero.");
                }
            }
            else
            {
                throw new SyntaticException(strSize + " não é um tamanho válido de vetor.");
            }
        }


        protected void AssertUserDefinedTypeExists(string typeId)
        {
            SymbolTableHelper.AssertUserDefinedTypeExists(typeId, Context);
        }

        protected void AssertVariableUndeclaredCurrentScope(string id)
        {
            SymbolTableHelper.AssertVariableUndeclaredCurrentScope(id, Context);
        }
    }
}
